iT邦幫忙

2024 iThome 鐵人賽

DAY 7
0
JavaScript

TypeScript Type Challenges 冒險篇章:30 天闖關之旅,type 簡單了?你確定?系列 第 7

第7關:Length of Tuple!TypeScript的三長兩短,給它量,很放心

  • 分享至 

  • xImage
  •  

第7關:Length of Tuple

關卡簡介

For given a tuple, you need create a generic Length, pick the length of the tuple

給定一個元組,實現一個泛型 Length,用來提取該元組的長度。

任務說明:

type tesla = ['tesla', 'model 3', 'model X', 'model Y']
type spaceX = ['FALCON 9', 'FALCON HEAVY', 'DRAGON', 'STARSHIP', 'HUMAN SPACEFLIGHT']

type teslaLength = Length<tesla>  // expected 4
type spaceXLength = Length<spaceX> // expected 5

接下來,你的任務是讓下面的type cases測試通過:

const tesla = ['tesla', 'model 3', 'model X', 'model Y'] as const
const spaceX = ['FALCON 9', 'FALCON HEAVY', 'DRAGON', 'STARSHIP', 'HUMAN SPACEFLIGHT'] as const

type cases = [
  Expect<Equal<Length<typeof tesla>, 4>>,
  Expect<Equal<Length<typeof spaceX>, 5>>,
]

冒險指南:

在這一關中,我們可以從以下幾個方向來思考:

  1. 如何確保 T 是一個 tuple ?
  2. 有哪些方式可以得到 array / tuple 的長度?

我們將會用到:

  1. extends:用於條件類型中,檢查一個類型是否符合另一個類型的約束。如果符合,則返回相應的類型;否則返回另一個類型。常用於檢查類型的兼容性。
  2. readonlyreadonly 關鍵字確保元組的元素是不可變的,即它的內容無法被修改。在這裡使用 readonly 是為了更準確地確保 T 是一個 tuple (元組),而不是普通的陣列
extends 在第三關已經介紹過,可以回到第三關參考喔!

通關方式:

在開始之前,讓我們先來看看如何定義和處理 tuple / array。

https://ithelp.ithome.com.tw/upload/images/20240921/20168789gwTAisJNUq.png

使用 as const 將 tesla 定義為 readonly ["tesla", "model 3", "model X", "model Y"],這意味著這是一個 readonly tuple 只讀元組。這樣的定義使得元組的每個元素和長度都是固定的,無法被修改。

當我們用 Length2<T extends any[]> 來獲取長度時,會出現錯誤,因為 Length2 要求 T 是可變的數組(any[])。但 tesla 變成了只讀類型,TypeScript 不允許將 readonly 的元組賦值給可變數組。

這個錯誤提示我們 readonly ["tesla", "model 3", "model X", "model Y"] 不能滿足 any[] 的約束,因為它是不可變的。為了解決這個問題,可以將 Length2 的約束改為 readonly any[],這樣就可以正常處理只讀元組,返回元組的長度。

解法1:

type Length<T extends readonly any[]> = T['length']

細節分析:

  • T extends readonly any[]:這部分確保了 T 是一個只讀的陣列或元組。通過加入 readonly,我們保證 T 的元素是不可變的,這在處理元組時尤為重要,因為元組是固定長度且元素類型明確的數組。使用 readonly 的原因是它限制了數組或元組的可變性,避免誤將元組視作普通的可變數組。
    • 為什麼需要 readonly:元組的特性在於它的固定長度和不變的元素類型。readonly 可以進一步加強這個特性,確保編譯器理解我們正在處理的是元組而非普通陣列。這樣做還能防止數組內容被修改,保證類型推斷的精確性。普通陣列的長度和元素類型都可以變動,而我們需要一個穩定、不可變的結構來確保正確的類型操作。
    • any[]:這個語法代表一個可以包含任何類型的陣列或元組。通過這樣的約束,我們確保泛型 T 必須是符合這個形狀的,也就是說,T 必須是一個陣列或元組,不允許傳入非陣列的類型。
  • T['length']:這是 TypeScript 中的一種索引類型語法,它允許我們直接訪問元組或陣列的 length 屬性。每個元組和陣列在 TypeScript 中都有一個內建的 length 屬性,用來表示它的長度。在這裡,我們使用 T['length'] 來提取元組 T 的長度。
    • 例子:假設我們有 type arr = [1, 2, 3],那麼 arr['length'] 的值就是 3,這是元組的實際長度。透過這樣的方式,我們能夠輕鬆地取得元組的長度並作為類型的一部分返回。
    type arr = [1, 2, 3];
    type lengthOfArr = arr['length']; // 3
    

這樣,我們就能順利通過測試啦 🎉 😭 🎉

總結:

本次介紹了 Length of Tuple 的實作,下一關會挑戰 exclude,期待再相見!


上一篇
第6關:First of Array!TypeScript 高要承認,挨打站穩:找出第一個元素
下一篇
第8關:Exclude!TypeScript稽查員:不合格的全都出去
系列文
TypeScript Type Challenges 冒險篇章:30 天闖關之旅,type 簡單了?你確定?13
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言